home *** CD-ROM | disk | FTP | other *** search
- //************************************************************************
- // PACK.C
- // Modul zur Datenkomprimierung
- // Idee und Implementierung tom ehlert '90
- //
- // Datenaufzeichnungsformat
- //
- // die Idee die dahintersteckt funktioniert wie folgt :
- // wenn der derzeitige String bereits gesendet worden ist, kodiere
- // ihn als kombination von index,laenge in die bereits empfangenen Daten
- // als 2-Bytekombination.
- //
- // Das genaue Format ist wohl am besten durch UNPACK beschrieben, man
- // macht dann auch keine Fehler in der Dokumentation.
- //
- // Das Schema laeuft wie folgt :
- //
- // Das jeweils erste Byte decodiert 8 Gruppen. Bit 7 (0x80) decodiert
- // die erste Gruppe,Bit 6 (0x40) die zweite usf. . Dabei gilt :
- // Bit == 0 --> Gruppe besteht aus 1 Byte, dieses ist in den
- // Zielpuffer zu kopieren.
- // Bit == 1 --> Gruppe besteht aus komprimierter Information,
- // lese zwei Byte.
- //
- // index = *pbuffer & SENDLEN (0x3ff);
- // length = (*pbuffer >> 12) + MIN_LENGTH;
- // if (length == 0x0f+MIN_LENGTH)
- // length = pbuffer[2]; /* code is 3 bytes */
- //
- // memcpy(outbuffer,outbuffer-index,length);
- //
- //
- //
- //************************************************************************
-
- #include <stdio.h>
- #include <setjmp.h>
- #include "pack.h"
- #include "huffman.h"
-
-
- typedef unsigned char uchar;
-
- #ifdef MSDOS
- #define ONLY_ON_80x86 /* this is ok */
- #else
- #define ONLY_ON_80x86 this runs only on 80x86 // BYTE - ORDER !!
- #endif
-
-
- #define MIN_LENGTH 3 /* minimum to be compressed */
- #define MAXCODELENGTH 0x0f
- #define IBSIZE 0xff
- #define SENDLEN 0xfff /* MUST BE 00001111111 */
-
- # define CRBLEN 0x800
-
- # define BUFFTAIL (SENDLEN+1)
- # define BUFFOVER 0x100
-
- #ifdef PACK
-
- static uchar sendbuff[ CRBLEN+BUFFTAIL+BUFFOVER] = {0};
- static int offset1 [1+CRBLEN+BUFFTAIL+BUFFOVER] = {0xffff,0};
- #define offset (offset1+1)
-
-
- #define NVH 0xffff
-
-
-
- //
- // Die gewaehlte HASH-Function ist beliebig; sie returned einen
- // Wert 0..HASH_SIZE. die vorgeschlagene bietet einen Kompromiss
- // zwischen sizeof(last(HASH_SIZE)) und Geschwindigkeit, diese
- // wird dadurch aber nicht wesentlich verringert
- //
- #define HASH_SIZE (0x400+0x200+0x100) // (0xff<<2) + (0xff<<1) + 0xff) ??
- #define HASH_VAL(ptr) ((ptr)[0] + ((ptr)[1]<<1) + ((ptr)[2] << 2))
-
- static int last[HASH_SIZE] = {0};
-
- #define add_list( c, cptr) offset[cptr] = last[c],last[c] = (cptr)
-
- /**********************************************************************
- ** output buffer waehrend des packens
- */
- static uchar far *packptr = NULL;
- static uchar far *packend = NULL;
-
- static uchar far *ibuffer = NULL;
- static unsigned short ilen = 0;
- static jmp_buf not_packable = {0};
-
- static uchar packmask = 0;
- static uchar packmaskbit = 0;
- static uchar far *packmaskptr = NULL;
-
- static int tosend = 0;
- static int gesendet = 0;
-
- #define STATIC
-
- STATIC void new_mask(void);
- STATIC void send1(void);
- STATIC void send(int len);
- STATIC void move_buffers(void);
- STATIC int xlen(void);
- STATIC void crunch(void);
- STATIC int rdf(unsigned char *d,unsigned len);
- extern int _fastcall memid(uchar *s1,uchar *s2);
-
- STATIC void new_mask(void)
- {
- *packmaskptr = packmask;
- packmaskptr = packptr++;
- packmaskbit = 0x80;
- packmask = 0x00;
- if (packptr >= packend)
- longjmp(not_packable,1);
- }
-
- STATIC void move_buffers(void)
- {
- register int *ip, loop,rd;
-
- memcpy(sendbuff,sendbuff+CRBLEN,BUFFTAIL+BUFFOVER);
- memcpy((uchar*)offset ,(uchar*)(offset +CRBLEN),
- sizeof(offset[0])*(BUFFTAIL+BUFFOVER));
- gesendet -= CRBLEN;
- tosend -= CRBLEN;
- while ((rd = rdf(sendbuff+tosend,sizeof(sendbuff)-tosend)) > 0)
- tosend += rd;
-
- for (ip = last,loop = LENGTH(last);loop ;ip++,--loop)
- if (*ip >= 0)
- *ip -= CRBLEN;
- for (ip = offset,loop = BUFFTAIL+BUFFOVER;loop ;ip++,--loop)
- if (*ip >= 0)
- *ip -= CRBLEN;
- }
-
-
- STATIC void crunch(void)
- {
- register int len,tbs,find_index;
-
- while ((tbs = tosend - gesendet) > 0)
- {
-
- //**********************************************************************
- // this part is essentially a subroutine, calculating len & find_index
- //**********************************************************************
- {
- register int sp;
- register int stop_ptr;
- register uchar *sbcheck;
- register short ccheck;
- register uchar *tbs = sendbuff + gesendet;
- register int loop;
-
- len = MIN_LENGTH-1;
-
- stop_ptr = gesendet - SENDLEN;
- if (stop_ptr < 0)
- stop_ptr = 0;
-
- ccheck = *(int*)(tbs+1);
- sbcheck = sendbuff+1;
-
- for (sp = last[HASH_VAL(tbs)];sp >= stop_ptr;sp = offset[sp])
- {
- if (*(short *)(sbcheck+sp) == ccheck)
- if ((loop = memid(sendbuff+sp,tbs)) > len)
- {
- len = loop;
- ccheck = *(short *)(tbs+len-1);
- sbcheck = sendbuff+len-1;
-
- find_index = gesendet - sp;
- if (len >= IBSIZE)
- break;
- }
- }
- }
-
- len = min(len,255);
- len = min(len,tbs);
-
-
-
- if (len >= MIN_LENGTH)
-
- //**********************************************************************
- // another inlined subroutine :
- // write len + index
- //**********************************************************************
-
- {
- register int index;register uchar *ibp;
-
- ONLY_ON_80x86;
-
- if (len < MAXCODELENGTH+MIN_LENGTH)
- { // remember : findindex <= SENDLEN !!
- *((int far *)packptr)++ = find_index | ((len -MIN_LENGTH) << 12) ;
- }
- else
- {
- *((int far *)packptr)++ = find_index | (MAXCODELENGTH << 12) ;
- *packptr++ = (uchar)len;
- }
-
- packmask |= packmaskbit;
- if ((packmaskbit >>= 1) == 0)
- new_mask();
-
- ibp = sendbuff+gesendet-1,index=gesendet-1;
- gesendet += len;
- for ( ; len ; ibp++,index++, --len)
- {
- register int hval = HASH_VAL(ibp);
- add_list(hval,index);
- }
-
- }
- else
- //**********************************************************************
- // another inlined subroutine :
- // write literal character
- //**********************************************************************
-
- {
- register uchar *s = sendbuff+gesendet; /* zu sendenden */
- register int hval;
-
- *packptr++ = *s++;
- if ((packmaskbit >>= 1) == 0)
- new_mask();
-
- hval = HASH_VAL(s-2);
- add_list(hval,gesendet-1);
- gesendet++;
-
- if (gesendet > CRBLEN +BUFFTAIL )
- move_buffers();
- }
-
- if (gesendet > CRBLEN +BUFFTAIL )
- move_buffers();
-
- }
- }
-
-
- STATIC int rdf(uchar *d,unsigned len)
- {
- len = min(len,ilen);
- memcpy(d,ibuffer,len);
- ilen -= len;
- ibuffer += len;
- return len;
- }
-
-
- int far _loadds pack(pbuffer,pbufferlen,inbuffer,blen)
- uchar far *pbuffer;short pbufferlen;
- uchar far *inbuffer;short blen;
- {
- int huff_length;
-
- if (blen == 0 || setjmp(not_packable))
- return 0xffff;
-
- ilen = blen;
- ibuffer = inbuffer;
- /* wenn man die naechsten zwei zeilen vertauscht */
- /* und -e eingeschaltet ist verhakelt sich MSC 6.00 */
- packend = pbuffer + pbufferlen - 25;
- packptr = pbuffer;
-
- if (packptr >= packend)
- longjmp(not_packable,1);
-
- packmaskptr = packptr++;
- packmaskbit = 0x80;
- packmask = 0x00;
-
- tosend = rdf(sendbuff,CRBLEN+BUFFTAIL+BUFFOVER);
- gesendet = 0;
-
- memset(last ,NVH,sizeof(last));
- memset(offset1,NVH,min(sizeof(offset1) , blen));
- gesendet = 0;
-
- crunch();
-
- *packmaskptr = packmask;
- if (packmaskbit == 0x80) // letztes newmask() zuviel
- packptr--;
-
- return packptr - pbuffer;
- }
- #endif
-
- #ifdef UNPACKC
-
- //*********************************************************************
- // this is the uncrunching part
- // unpackc() is written in C
- // unpack() see UNPACK.ASM
- // both routines work identical
- //*********************************************************************
-
- int far _loadds unpackc(outbuffer,pbuffer,packlen)
- uchar far *outbuffer;
- uchar far *pbuffer;register int packlen;
- {
- register int uloop;
- register uchar packmask;
- int length;unsigned index;
- uchar far *sbuffer = outbuffer;
-
- for (uloop = 1;packlen > 0;packmask <<= 1)
- {
- if (--uloop == 0)
- {
- packmask = *pbuffer++,packlen--;
- uloop = 8;
- }
- if ((packmask & 0x80) == 0) /* this byte is literally */
- *outbuffer++ = *pbuffer++,packlen--;
- else
- { /* next 2 bytes coded */
- ONLY_ON_80x86;
- index = *(int far *)pbuffer; /* 4 bit length */
- length = (index >> 12) + MIN_LENGTH;/* 12 bit offset */
- index &= SENDLEN;
- if (length == MAXCODELENGTH+MIN_LENGTH) /* length > 18 */
- { /* use next byte for length*/
- length = pbuffer[2]; /* code is 3 bytes */
- pbuffer += 3;
- packlen -= 3;
- }
- else {
- packlen -= 2;
- pbuffer += 2;
- }
- /* copy BYTEWISE with OVERWRITE */
- if (index == 1) // memcpy will not work as it copies WORDS
- memset(outbuffer,*(outbuffer-1),length);
- else
- memcpy(outbuffer,outbuffer-index,length);
-
- outbuffer += length;
- }
- }
- return outbuffer-sbuffer;
- }
-
- #endif
-
- //***********************************************************************
- // externe Assmblerroutinen :
- //
- // memidc(uchar *dest,uchar *src)
- // // return number of equal bytes
- // {
- // register uchar *dr = dest;
- //
- // for (; *src++ == *dr ;dr++)
- // ;
- // return dr-dest;
- // }
- //***********************************************************************
-